import {defineConfig, loadEnv, Plugin, type ProxyOptions} from 'vite'
import {resolve} from 'path'
import vue from "@vitejs/plugin-vue";
import vueSetupExtend from "vite-plugin-vue-setup-extend";
import UnoCSS from "unocss/vite";
import {presetAttributify, presetIcons, presetUno} from "unocss";
import AutoImport from "unplugin-auto-import/vite";
import Icons from "unplugin-icons/vite";
import {FileSystemIconLoader} from "unplugin-icons/loaders";
import IconsResolver from "unplugin-icons/resolver";
import {createSvgIconsPlugin} from "vite-plugin-svg-icons";
import ViteCompression from "vite-plugin-compression";
import {visualizer} from "rollup-plugin-visualizer";
import type {ImportMetaEnv} from "./src/env"
import Components from "unplugin-vue-components/vite";
import {NaiveUiResolver} from "unplugin-vue-components/resolvers";
import GenerateComponentName from 'unplugin-generate-component-name/vite'

const root = process.cwd()
const pathResolve = (dir: string): string => {
    return resolve(__dirname, '.', dir);
}

const wrapperEnv = (envConf: Record<string, string>): ImportMetaEnv => {
    console.log(envConf);
    return <ImportMetaEnv>{
        VITE_APP_CLIENT_ID: envConf['VITE_APP_CLIENT_ID'],
        VITE_APP_CLIENT_SECRET: envConf['VITE_APP_CLIENT_SECRET'],
        VITE_COMPRESS_TYPE: envConf['VITE_COMPRESS_TYPE'] ?? 'gzip',
        VITE_USE_COMPRESS: false,
        VITE_APP_TITLE: envConf['VITE_APP_TITLE'],
        VITE_API_URL: envConf['VITE_API_URL'],
        VITE_APP_PORT: Number(envConf['VITE_APP_PORT']),
        VITE_PUBLIC_URL: envConf['VITE_PUBLIC_URL'],
        VITE_API_PROXY: envConf['VITE_API_PROXY'] ? JSON.parse(envConf['VITE_API_PROXY'].replace(/'/g, '"')) : ''
    }
}

type ProxyItem = [string, string]
type ProxyList = ProxyItem[]
type ProxyTargetList = Record<string, ProxyOptions>

const createProxy = (list: ProxyList): ProxyTargetList => {
    const result: ProxyTargetList = {}
    for (let [prefix, target] of list) {
        const isHttps = /^https:\/\//.test(target);
        result[prefix] = {
            target,
            changeOrigin: true,
            ws: true,
            rewrite: path => path.replace(new RegExp(`${prefix}`), ''),
            secure: isHttps
        }
    }
    return result;
}

const setPlugins = (env: ImportMetaEnv, isBuild: boolean): Plugin[] => {
    const result = [
        vue(),
        vueSetupExtend(),
        UnoCSS({
            presets: [
                presetUno(),
                presetAttributify(),
                presetIcons()
            ]
        }),
        AutoImport({
            dts: 'src/auto-import.d.ts',
            imports: [
                'vue',
                {
                    'naive-ui': [
                        'useDialog',
                        'useMessage',
                        'useNotification',
                        'useLoadingBar'
                    ]
                }
            ]
        }),
        Icons({
            compiler: 'vue3',
            autoInstall: true,
            customCollections: {
                custom: FileSystemIconLoader(resolve(__dirname, 'src/assets/icons'))
            },
            defaultClass: 'inline-block',
        }),
        Components({
            resolvers: [NaiveUiResolver(), IconsResolver({customCollections: ['custom'], prefix: 'icon'})],
            dts: 'src/components.d.ts',
        }),
        createSvgIconsPlugin({
            iconDirs: [resolve(process.cwd(), 'src/assets/icons')],
            symbolId: 'icon-custom-[dir]-[name]',
            inject: 'body-last',
            customDomId: '__CUSTOM_SVG_ICON__'
        }),
        GenerateComponentName({
            include: ['**/*.vue'],
            enter: [{
                include: ["**/*index.vue"],
                genComponentName: ({attrName, dirname, originalName}) => attrName ?? `${dirname}-${originalName}`
            }]
        }),
    ] as Plugin[];
    if (env.VITE_USE_COMPRESS) {
        result.push(ViteCompression({
            algorithm: env.VITE_COMPRESS_TYPE ?? 'gzip',
        }));
    }
    if (isBuild) {
        result.push(visualizer({
            open: true,
            gzipSize: true,
            brotliSize: true,
        }))
    }
    return result
}

export default defineConfig(({mode, command}) => {
    const isBuild = command === 'build';
    const env = wrapperEnv(loadEnv(mode, root));
    return {
        root,
        base: env.VITE_PUBLIC_URL,
        resolve: {
            alias: {
                '@': pathResolve('src')
            }
        },
        server: {
            open: true,
            host: "0.0.0.0",
            port: env.VITE_APP_PORT,
            proxy: createProxy(env.VITE_API_PROXY)
        },
        plugins: setPlugins(env, isBuild)
    }
})
